from socket import *
import threading
import sys
import time,re
import urllib
from Globals import *

blockClient = None
blockTime = 0

class SetupServer():
	serversocket = None
	def __init__(self,port,callback):
		print "Setting up a server on port " + str(port)
		hook.runHooks('setupServer_before', port=port, callback=callback)
		self.port = port
		self.callback = callback
		self.startServer('0.0.0.0')

	def startServer(self,host):
		addr = (host, self.port)   
		try:
			serversocket = socket(AF_INET, SOCK_STREAM)
			serversocket.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
			serversocket.bind(addr)
			serversocket.listen(0)            
			t = threading.Thread(target=Listener,args=(serversocket,self.port,self.callback,))
			t.start()
		except:
			print "Server error " + str(sys.exc_info())
			sys.exit(1)        
				
	def killServer(self):
		self.serversocket.close()
		sys.exit(1);  

class Listener():
	def __init__(self,serversocket,port,callback):
		self.port = port
		self.callback = callback
		self.listen(serversocket)

	def listen(self,serversocket):
		while 1:
			clientsocket, clientaddr = serversocket.accept()          
			t = threading.Thread(target=ServerFinder,args=(self.port,clientsocket,self.callback,))
			t.start()

class Server(object):
	client = None
	port = 0
	def __init__(self,clientsocket):
		hook.runHooks('server_init', clientsocket=clientsocket)
		self.client = clientsocket

	def setCallback(self, callback):
		hook.runHooks('setCallback_before', callback=callback)
		self.callback = callback
		self.handler(self.client)

	def handler(self,client):
		global blockTime, blockClient
		while 1:
			try:
				self.client.send("mc~# ")

				data = self.client.recv(1024)
				hook.runHooks('handler_loop', client=client, data=data, callback=self.callback)
				if not data:
					break
				elif len(data) > 1:
					if blockClient != None:
						now = int(time.time())
						timeExpired = now - blockTime
						if timeExpired > 180:
							blockClient = None

					if blockClient == None or blockClient == self.client:
						if re.match('^(next|skip)$',data):
							hook.runHooks('nextCommand_before', clientsocket=client, callback=self.callback)
							self.callback.skipSong(1)
						elif re.match('^(previous|back)$',data):
							hook.runHooks('nextCommand_before', clientsocket=client, callback=self.callback)
							self.callback.skipSong(-1)	
						elif re.match('^stop$', data):
							hook.runHooks('stopCommand_before', clientsocket=client, callback=self.callback)
							self.callback.stopPlaying()
						elif re.match('^\-$', data):
							hook.runHooks('volumeDownCommand_before', clientsocket=client, callback=self.callback)
							self.callback.volumeDown()
						elif re.match('^\+$', data):
							hook.runHooks('volumeUpCommand_before', clientsocket=client, callback=self.callback)
							self.callback.volumeUp()
						elif re.match('^yt', data):
							hook.runHooks('playCommand_before', clientsocket=client, callback=self.callback)
							parts = data.split('yt ')
							self.callback.playSong(parts[1])
						elif re.match('^block$', data):
							hook.runHooks('blockCommand_before', clientsocket=client, callback=self.callback)
							blockClient = self.client
							blockTime = int(time.time())
							self.client.send("You have blocked the MediaController for 180 seconds.\n")
						elif re.match('^unblock$', data):
							hook.runHooks('unblockCommand_before', clientsocket=client, callback=self.callback)
							blockClient = None
							blockTime = int(time.time())
							self.client.send("You have unblocked the MediaController.\n")
						else:
							hook.runHooks('unhandledCommand_before', clientsocket=client, data=data, callback=self.callback)
					else:
						self.client.send("MediaController is blocked.\n")
						hook.runHooks('clientBlocked_before', clientsocket=client, callback=self.callback)
			except: 
				for err in sys.exc_info():
					print str(err)       
				break


class Raw(Server):
	port = 3333
	callback = None
	def __init__(self,clientsocket):
		super(Raw, self).__init__(clientsocket)

	@classmethod
	def isHandler(cls,port):
		return cls.port == port

class HTTP(Server):
	port = 3334
	def __init__(self,clientsocket):
		super(HTTP, self).__init__(clientsocket)

	@classmethod
	def isHandler(cls,port):
		return cls.port == port

def ServerFinder(port,clientsocket,callback):
	for cls in Server.__subclasses__():
		if cls.isHandler(port):
			c = cls(clientsocket)
			c.setCallback(callback)
			return c
